#include "../include/log/log_system.hpp"
#include <vector>
#include <thread>
#include <chrono>

void bench(const std::string &logger_name, size_t thread_count, size_t message_count, size_t message_len) // 性能测试
{
    // 获取日志器
    log_system::Logger::pointer logger = log_system::getLogger(logger_name);
    if(logger.get() == nullptr)
        return;
    std::cout << "测试日志：" << message_count << " 条， 总大小：" << (message_count * message_len) / 1024 << "KB" << std::endl;
    // 组织指定长度的日志消息
    std::string message(message_len - 1, 'A'); // 少一个字节，是为了给末尾到时候添加换行
    // 创建指定数量的线程
    std::vector<std::thread> threads;
    std::vector<double> cost_array(thread_count);
    size_t message_prt_thr = message_count / thread_count; // 每个线程要输出的日志数量 = 总日志数量 / 线程数量
    for(int i = 0; i < thread_count; i++)
    {
        threads.emplace_back([&, i](){
            // 线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            // 开始循环写日志
            for(int j = 0; j < message_prt_thr; j++)
            {
                logger->fatal("%s", message.c_str());
            }
            // 线程函数内部结束计时
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_array[i] = cost.count();
            std::cout << "\t线程" << i << ": " << "\t输出日志数量: " << message_prt_thr << ", 耗时" << cost.count() << "s" << std::endl;
        });
    }
    for(int i = 0; i < thread_count; i++)
    {
        threads[i].join();
    }
    // 计算总耗时：在多线程中每个线程都会耗费时间，但是线程是并发处理的，所以耗时最高的那个线程的时间就是总时间
    double max_cost = cost_array[0];
    for(int i = 0; i < thread_count; i++)
    {
        max_cost = max_cost < cost_array[i] ? cost_array[i] : max_cost;
    }
    size_t message_per_sec = message_count / max_cost;
    size_t size_per_sec = (message_count * message_len) / (max_cost * 1024);
    // 进行输出打印
    std::cout << "\t总耗时: " << max_cost << "s" << std::endl;
    std::cout << "\t每秒输出日志数量: " << message_per_sec << "条" << std::endl;
    std::cout << "\t每秒输出日志大小: " << size_per_sec << "KB" << std::endl;
}

void sync_bench() // 同步日志器
{
    std::unique_ptr<log_system::LoggerBuilder> builder(new log_system::GlobalLoggerBuilder());
    builder->buildLoggerType(log_system::LoggerBuilder::Type::LOGGER_SYNC);
    builder->buildLoggerName("SYNC_LOGGER");
    builder->buildFormatter("%m%n");
    builder->buildLoggerSink<log_system::SpecifyFileLogSink>("./logfile/sync.log");
    builder->build();
    // bench("SYNC_LOGGER", 1, 1000000, 100); //单线程

    bench("SYNC_LOGGER", 3, 1000000, 100); //多线程
} 

void async_bench() // 异步日志器
{
    std::unique_ptr<log_system::LoggerBuilder> builder(new log_system::GlobalLoggerBuilder());
    builder->buildLoggerType(log_system::LoggerBuilder::Type::LOGGER_ASYNC);
    builder->buildLoggerName("ASYNC_LOGGER");
    builder->buildFormatter("%m%n");
    builder->buildLoggerSink<log_system::SpecifyFileLogSink>("./logfile/async.log");
    builder->build();
    // bench("ASYNC_LOGGER", 1, 1000000, 100); // 单线程

    bench("ASYNC_LOGGER", 3, 1000000, 100); // 多线程
} 

int main()
{
    // sync_bench();
    async_bench();
    return 0; 
}